package cn.buk.tms.eotms.service;

import cn.buk.api.pay.alipay.service.AlipayService;
import cn.buk.common.JsonResult;
import cn.buk.common.flight.dto.FlightInfoDto;
import cn.buk.common.util.DateUtil;
import cn.buk.tms.common.constant.TmsOrderConstant;
import cn.buk.tms.common.dto.base.BaseOrderDto;
import cn.buk.tms.eotms.dao.*;
import cn.buk.tms.eotms.dto.CarOrderDto;
import cn.buk.tms.eotms.dto.RoleInfo;
import cn.buk.tms.eotms.dto.VasOrderDto;
import cn.buk.tms.eotms.dto.VasOrderPassengerDto;
import cn.buk.tms.eotms.entity.*;
import cn.buk.tms.eotms.sc.SearchFlightOrderCriteria;
import cn.buk.tms.exception.BaseException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import static cn.buk.tms.common.constant.TmsOrderConstant.*;

/**
 * @author yfdai
 */
@Service
public class VasOrderServiceImpl extends BaseAbstractService implements VasOrderService {

  private final static Logger logger = LogManager.getLogger(VasOrderServiceImpl.class);

  public VasOrderServiceImpl(VasOrderDao vasOrderDao,
                             FlightOrderDao flightOrderDao,
                             OrderNoGenerator orderNoGenerator,
                             PaymentOrderDao paymentOrderDao,
                             AlipayService alipayService) {
    this.vasOrderDao = vasOrderDao;
    this.flightOrderDao = flightOrderDao;
    this.orderNoGenerator = orderNoGenerator;
    this.paymentOrderDao = paymentOrderDao;
    this.alipayService = alipayService;
  }

  private final VasOrderDao vasOrderDao;
  private final FlightOrderDao flightOrderDao;
  private final OrderNoGenerator orderNoGenerator;
  private final PaymentOrderDao paymentOrderDao;
  private final AlipayService alipayService;

  @Override
  public List<VasOrderDto> searchVasOrders(int userId, SearchFlightOrderCriteria sc, final boolean isInsurance) {
    final int ownerId = getOwnerIdByUserId(userId);
    final int customerId = getCustomerIdByUserId(userId);
    final int enterpriseId = getEnterpriseIdByUserId(userId);
    final String username = getUsernameByUserId(userId);

    Set<String> roles = getRolesByUserId(enterpriseId, userId);
    //管理员可以查看所有的员工信息
    //其它可以查看本部门所有的员工信息
    if (roles.contains(RoleInfo.ROLE_ADMIN)) {
      //管理员可以查看所有部门的订单
    } else if (roles.contains(RoleInfo.ROLE_MANAGER) || roles.contains(RoleInfo.ROLE_APPROVER)){
      //只能查看本部门的
      int deptId = getCustomerDeptIdByUserId(userId);
      sc.setDepartmentId(deptId);
    } else {
      //只能查看自己的订单
      sc.setOp1(username);
    }

    List<VasOrder> orders = vasOrderDao.searchVasOrders(ownerId, customerId, sc, isInsurance);

    return convertToVasOrderDto(orders);
  }

  @Override
  public VasOrderDto getVasOrderById(int userId, int id) {
    final int ownerId = getOwnerIdByUserId(userId);
    final int customerId = getCustomerIdByUserId(userId);

    VasOrder o = vasOrderDao.getOrderById(id);
    if (o == null || o.getEnterpriseId() != ownerId || o.getCustomer().getId() != customerId) {
      VasOrderDto dto = new VasOrderDto();
      dto.setErrcode(40000);
      dto.setErrmsg("无此订单");
      return dto;
    }

    cleanVasOrder(o);

    VasOrderDto dto = VasOrderDto.createByVasOrder(o);
    searchVasOrderFlights(dto);

    if (dto.getBlanketOrderId() != null && dto.getBlanketOrderId() > 0) {
      //获取上级订单或子订单
      BlanketOrder parentOrder = flightOrderDao.searchParentOrder(ownerId, dto.getBlanketOrderId());
      if (parentOrder != null) {
        if (parentOrder.getActualOrderType() == ORDER_TYPE_FLIGHT) {
          FlightOrder flightOrder = flightOrderDao.getOrderById(parentOrder.getActualOrderId());

          BaseOrderDto baseOrderDto = new BaseOrderDto();
          baseOrderDto.setId(flightOrder.getId());
          baseOrderDto.setOrderType(ORDER_TYPE_FLIGHT);
          baseOrderDto.setOrderNo(flightOrder.getOrderNo());
          baseOrderDto.setOrderStatus(flightOrder.getStatus());

          dto.setParentOrder(baseOrderDto);
        }
      }
    }

    dto.setErrcode(0);

    return dto;
  }

  /**
   * 创建机场服务订单，通过接口远程提交
   * @param userId
   * @param operator
   * @param dto
   * @return
   */
  @Override
  public JsonResult createVaasOrder(final int userId, final String operator, final VasOrderDto dto) throws BaseException {
    if (dto == null || dto.getProductCode().length() == 0
            || dto.getProductName().length() == 0) {
      return JsonResult.createJsonResult(-1, "产品代码、产品名称是必需的。");
    }

    final int customerId = getCustomerIdByUserId(userId);
    final int owner = getOwnerIdByUserId(userId);
    dto.setCustomerId(customerId);

    Customer customer = null;
    if (dto.getCustomerId() > 0) {
      customer = customerDao.getCustomerById(dto.getCustomerId());
      if (customer == null || customer.getEnterpriseId() != owner) {
        return JsonResult.createJsonResult(-3, "该客户不存在");
      }
    }

    if (dto.getPassengers().size() == 0) {
      return JsonResult.createJsonResult(-4, "需要填写客人信息");
    }

    for (VasOrderPassengerDto psgDto : dto.getPassengers()) {
      if (psgDto.getName().length() < 2) {
        return JsonResult.createJsonResult(-5, "需要填写客人的名字");
      }
    }

    if (dto.getFlights() != null && dto.getFlights().size() > 0) {
      //校验航班信息
      //此处只需要检验出发、到达、日期、航班号
      for(FlightInfoDto flt: dto.getFlights()) {
        validateFlightInfo(flt, true);
      }
    }

    dto.setOrderType(VasOrder.VAS_ORDER_TYPE_VAAS);

    return doCreateVasOrder(owner, operator, dto, customer, null);
  }

  @Override
  public JsonResult payVaasOrder(int userId, int orderId) {
    VasOrderDto orderDto = this.getVasOrderById(userId, orderId);
    if (orderDto == null || orderDto.getErrcode() != 0) {
      return JsonResult.createJsonResult(-1, "无此订单");
    }

    if (orderDto.getPayType() != PAY_TYPE_CASH) {
      return JsonResult.createJsonResult(-1, "该订单的付款方式非现金方式");
    }

    final int enterpriseId = getEnterpriseIdByUserId(userId);
    final int ownerId = getOwnerIdByUserId(userId);

    //支付订单号
    // 10 - 支付宝支付
    // 20 - 表示微信支付
    String outTradeNo = "10"+ enterpriseId + "0" + + userId + "0" + DateUtil.getCurDateTimeString("yyyyMMddHHmmss");
    //商户网站订单系统中唯一订单号，必填

    //订单名称
    final String subject = "机场服务订单付款";
    //必填

    //保存支付订单
    PaymentOrder order = new PaymentOrder();
    order.setEnterpriseId(enterpriseId);
    order.setUserId(userId);
    order.setOwnerEnterpriseId(ownerId);
    order.setTradeNo(outTradeNo);
    order.setPrice(orderDto.getTotal());
    order.setStatus(0);
    order.setMemo(subject);
    order.setOrderType(ORDER_TYPE_SERVICE);
    order.setOrderId(orderId);

    JsonResult jsonResult = new JsonResult();

    jsonResult.setStatus("OK");
    int retCode = paymentOrderDao.create(order);

    String url = alipayService.createPaymentParams(outTradeNo, orderDto.getTotal(), subject);

    logger.info(url);

    jsonResult.setUrl(url);

    return jsonResult;
  }

  private JsonResult doCreateVasOrder(final int ownerId, final String operator, VasOrderDto dto, Customer customer, TieInProduct serviceProduct) {
    final int productType = TieInProduct.THIRD_VAS_PRODUCT;

    VasOrder info = new VasOrder();
    BeanUtils.copyProperties(dto, info, "flights", "passengers");

    //产品类型
    info.setProductType(productType);

    info.setCreateDate(DateUtil.getCurDate());
    info.setOperator(operator);
    info.setEnterpriseId(ownerId);

    // 其它vas订单
    info.setOrderNo(orderNoGenerator.generateOrderNo(ownerId, TmsOrderConstant.ORDER_NO_VAS));

    if (dto.getCustomerId() == 0) {
      //散客
      info.setCustomerType(0);
    } else {
      info.setCustomerType(1);
      info.setCustomer(customer);
    }

    info.setPassengers(null);
    for (VasOrderPassengerDto psgDto : dto.getPassengers()) {
      VasOrderPassenger psg = new VasOrderPassenger();
      BeanUtils.copyProperties(psgDto, psg);

      psg.setEnterpriseId(ownerId);
      psg.setOrder(info);

      info.getPassengers().add(psg);
    }

    info.setFlights(null);
    if (dto.getFlights().size() > 0) {
      for (FlightInfoDto fltDto : dto.getFlights()) {
        VasOrderFlight flt = new VasOrderFlight();
        flt.setEnterpriseId(ownerId);
        flt.setId(0);

        BeanUtils.copyProperties(fltDto, flt.getFlight());

        flt.getFlight().setDepartureDate(DateUtil.formatDate(fltDto.getDdate(), "yyyy-MM-dd"));
        flt.setOrder(info);

        info.getFlights().add(flt);
      }
    }

    if (info.getOrderType() == VasOrder.VAS_ORDER_TYPE_VAAS && info.getFlights().size() != 1) {
      return JsonResult.createJsonResult(-7, "机场服务订单目前仅支持单程服务订单");
    }

    int retCode = vasOrderDao.createVasOrder(info);

    return JsonResult.createJsonResult(retCode);
  }


  private List<VasOrderDto> convertToVasOrderDto(List<VasOrder> orders) {
    cleanVasOrders(orders);

    List<VasOrderDto> dtos = new ArrayList<>();
    for (VasOrder order : orders) {
      VasOrderDto dto = VasOrderDto.createByVasOrder(order);
      searchVasOrderFlights(dto);

      dtos.add(dto);
    }

    return dtos;
  }

  private void cleanVasOrders(List<VasOrder> orders) {
    for (VasOrder vasOrder : orders) {
      cleanVasOrder(vasOrder);
    }
  }

  private void cleanVasOrder(VasOrder vasOrder) {
    for (VasOrderPassenger psg : vasOrder.getPassengers()) {
      psg.setOrder(null);
    }

    for (VasOrderFlight flt : vasOrder.getFlights()) {
      flt.setOrder(null);
    }
  }

  /**
   * 目前vasOrder中还没有保存航班信息，所以需要从关联的机票订单中查找
   */
  private void searchVasOrderFlights(VasOrderDto o) {
    if (o.getFlights().size() > 0) {
      return;
    }

    if (o.getFlightOrderId() > 0) {
      // 获取航班信息
      List<FlightOrderFlight> flights = flightOrderDao
          .searchFlightOrderFlights(o.getFlightOrderId());
      for (FlightOrderFlight flight0 : flights) {
        flight0.setOrder(null);

        FlightInfoDto flight1 = new FlightInfoDto();
        BeanUtils.copyProperties(flight0.getFlight(), flight1);

        try {
          flight1.setDdate(DateUtil.convertToDate(flight0.getFlight().getDdate(), "yyyy-MM-dd"));
        } catch (Exception ignored) {

        }

        o.getFlights().add(flight1);
      }
    }
  }
}
